<?php

/**
 * Some rights reserved：abc3210.com
 * Contact email:admin@abc3210.com
 */
class TagLibShuipf extends TagLib {

    protected $tags = array(
        //内容标签
        'content' => array('attr' => 'action,cache,num,page,return,pagetp,pagefun', 'level' => 3),
        //Tags标签
        'tags' => array('attr' => 'action,cache,num,page,return,pagetp,pagefun', 'level' => 3),
        //评论标签
        'comment' => array('attr' => 'action,cache,num,return', 'level' => 3),
        //友情链接标签
        'links' => array('attr' => 'action,cache,num,return', 'level' => 3),
        //推荐位标签
        'position' => array('attr' => 'action,cache,num,return', 'level' => 3),
        //SQL标签
        'get' => array("attr" => 'sql,cache,page,dbsource,return', 'level' => 3),
        //模板标签
        'template' => array("attr" => "file", "close" => 0),
    );

    /**
     * 模板包含标签 {template file=""}
     * @staticvar array $_templateParseCache
     * @param type $attr
     * @param type $content
     * @return array 
     */
    public function _template($attr, $content) {
        static $_templateParseCache = array();
        $cacheIterateId = md5($attr . $content);
        if (isset($_templateParseCache[$cacheIterateId])) {
            return $_templateParseCache[$cacheIterateId];
        }
        //检查CONFIG_THEME是否被定义
        if (!defined("CONFIG_THEME")) {
            return;
        }
        $tag = $this->parseXmlAttr($attr, 'template');
        $TemplatePath = TEMPLATE_PATH . CONFIG_THEME . "/" . $tag['file'];
        //判断模板是否存在
        if (!file_exists_case($TemplatePath)) {
            return;
        }
        //读取内容
        $tmplContent = file_get_contents($TemplatePath);
        $parseStr = $this->tpl->parse($tmplContent);
        $_templateParseCache[$cacheIterateId] = $parseStr;
        return $_templateParseCache[$cacheIterateId];
    }

    /**
      +----------------------------------------------------------
     * content标签解析 循环输出数据集
     * 格式：
     * <content action="lists" catid="$catid"  order="id DESC" num="4" page="$page">
     * {user.username}
     * </content>
     * 
      +----------------------------------------------------------
     * 可调用类型 action
     * lists	 内容数据列表
     * relation	 内容相关文章
     * hits	 内容数据点击排行榜
     * category	 内容栏目列表
      +----------------------------------------------------------
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     * @param string $attr 标签属性
     * @param string $content  标签内容
      +----------------------------------------------------------
     * @return string|void
      +----------------------------------------------------------
     */
    public function _content($attr, $content) {
        static $_iterateParseCache = array();
        //如果已经解析过，则直接返回变量值
        $cacheIterateId = md5($attr . $content);
        if (isset($_iterateParseCache[$cacheIterateId]))
            return $_iterateParseCache[$cacheIterateId];
        $tag = $this->parseXmlAttr($attr, 'content');
        /* 属性列表 */
        $num = (int) $tag['num']; //每页显示总数
        $page = $tag['page']; //当前分页
        $pagefun = empty($tag['pagefun']) ? "page" : $tag['pagefun']; //分页函数，默认page
        $return = empty($tag['return']) ? "data" : $tag['return']; //数据返回变量
        $action = $tag['action']; //方法
        $pagetp = $tag['pagetp']; //分页模板

        $parseStr = '<?php';
        $parseStr .= ' $content_tag = TagLib("Content");';
        //如果有传入$page参数，则启用分页。
        if (isset($page)) {
            $tag = array_merge($tag, array(
                "count" => '$count',
                'limit' => '$_page_->firstRow.",".$_page_->listRows'
                    ));
            $parseStr .= ' $count = $content_tag->count(' . self::arr_to_html($tag) . ');';
            $parseStr .= ' $_GET[C("VAR_PAGE")] = $page;';
            $parseStr .= ' $pagetp = "' . $pagetp . '";';
            $parseStr .= ' $_page_ = ' . $pagefun . '($count ,' . $num . ',$page,6,C("VAR_PAGE"),"",true,$pagetp);';
            //使用常量来保存总分页数，有个缺陷，如果不使用跳转的方式生成，会出现生成下一个栏目的时候无法对该常量进行重新赋值，使用跳转生成下一个栏目则没有这个问题！
            $parseStr .= ' if (!defined("PAGES"))define("PAGES", $_page_->Total_Pages);';
            //_PAGES_ 用于解决上述所说的问题，这样可以根据$_GET["_PAGES_"] 来判断要生成多少页了
            $parseStr .= ' $_GET["_PAGES_"] = $_page_->Total_Pages;';
            $parseStr .= ' $pages = $_page_->show("default");';
            $parseStr .= ' $pagesize = ' . $num . ';';
            $parseStr .= ' $offset = ($page - 1) * $pagesize;';
        }
        $parseStr .= ' if(method_exists($content_tag, "' . $action . '")):';
        $parseStr .= ' $' . $return . ' = $content_tag->' . $action . '(' . self::arr_to_html($tag) . ');';
        $parseStr .= ' endif;';
        
        $parseStr .= ' ?>';
        $parseStr .= $this->tpl->parse($content);
        $_iterateParseCache[$cacheIterateId] = $parseStr;
        return $parseStr;
    }

    /**
     * 评论标签
     *  +----------------------------------------------------------
     * get_comment 获取评论总数
     * 格式：
     * <comment action="get_comment" catid="$catid" id="$id">
     * {$data.total}
     * </comment>
     * 
     * get_comment  lists  bang
      +----------------------------------------------------------
     * @param string $attr 标签属性
     * @param string $content  标签内容
     */
    public function _comment($attr, $content) {
        static $_iterateParseCache = array();
        //如果已经解析过，则直接返回变量值
        $cacheIterateId = md5($attr . $content);
        if (isset($_iterateParseCache[$cacheIterateId]))
            return $_iterateParseCache[$cacheIterateId];
        $tag = $this->parseXmlAttr($attr, 'content');
        /* 属性列表 */
        $num = (int) $tag['num']; //每页显示总数
        $return = empty($tag['return']) ? "data" : $tag['return']; //数据返回变量
        $action = $tag['action']; //方法
        
        $parseStr = '<?php';
        $parseStr .= ' $comment_tag = TagLib("Comment");';
        $parseStr .= ' if(method_exists($comment_tag, "' . $action . '")):';
        $parseStr .= ' $' . $return . ' = $comment_tag->' . $action . '(' . self::arr_to_html($tag) . ');';
        $parseStr .= ' endif;';
        $parseStr .= ' ?>';
        $parseStr .= $this->tpl->parse($content);
        $_iterateParseCache[$cacheIterateId] = $parseStr;
        return $parseStr;
    }
    
    /**
     * Tags标签
     *  +----------------------------------------------------------
     * list 列表
     * 格式：
     * <tags action="lists" tag="$tag" tagid="$tagid" num="4" page="$page" order="id DESC">
     * {$data.total}
     * </tags>
     * 
     * lists top
      +----------------------------------------------------------
     * @param string $attr 标签属性
     * @param string $content  标签内容
     */
    public function _tags($attr, $content) {
        static $_iterateParseCache = array();
        //如果已经解析过，则直接返回变量值
        $cacheIterateId = md5($attr . $content);
        if (isset($_iterateParseCache[$cacheIterateId]))
            return $_iterateParseCache[$cacheIterateId];
        $tag = $this->parseXmlAttr($attr, 'content');
        /* 属性列表 */
        $num = (int) $tag['num']; //每页显示总数
        $page = $tag['page']; //当前分页
        $pagefun = empty($tag['pagefun']) ? "page" : $tag['pagefun']; //分页函数，默认page
        $return = empty($tag['return']) ? "data" : $tag['return']; //数据返回变量
        $action = $tag['action']; //方法
        $pagetp = $tag['pagetp']; //分页模板

        $parseStr = '<?php';
        $parseStr .= ' $Tags_tag = TagLib("Tags");';
        //如果有传入$page参数，则启用分页。
        if (isset($page)) {
            $tag = array_merge($tag, array(
                "count" => '$count',
                'limit' => '$_page_->firstRow.",".$_page_->listRows'
                    ));
            $parseStr .= ' $count = $Tags_tag->count(' . self::arr_to_html($tag) . ');';
            $parseStr .= ' $_GET[C("VAR_PAGE")] = $page;';
            $parseStr .= ' $pagetp = "' . $pagetp . '";';
            $parseStr .= ' $_page_ = ' . $pagefun . '($count ,' . $num . ',$page,6,C("VAR_PAGE"),"",true,$pagetp);';
            //使用常量来保存总分页数，有个缺陷，如果不使用跳转的方式生成，会出现生成下一个栏目的时候无法对该常量进行重新赋值，使用跳转生成下一个栏目则没有这个问题！
            $parseStr .= ' if (!defined("PAGES"))define("PAGES", $_page_->Total_Pages);';
            //_PAGES_ 用于解决上述所说的问题，这样可以根据$_GET["_PAGES_"] 来判断要生成多少页了
            $parseStr .= ' $_GET["_PAGES_"] = $_page_->Total_Pages;';
            $parseStr .= ' $pages = $_page_->show("default");';
            $parseStr .= ' $pagesize = ' . $num . ';';
            $parseStr .= ' $offset = ($page - 1) * $pagesize;';
        }
        $parseStr .= ' if(method_exists($Tags_tag, "' . $action . '")):';
        $parseStr .= ' $' . $return . ' = $Tags_tag->' . $action . '(' . self::arr_to_html($tag) . ');';
        $parseStr .= ' endif;';
        
        $parseStr .= ' ?>';
        $parseStr .= $this->tpl->parse($content);
        $_iterateParseCache[$cacheIterateId] = $parseStr;
        return $parseStr;
    }

    /**
     * 友情链接标签
     *  +----------------------------------------------------------
     * type_list 获取友情链接列表
     * 格式：
     * <links action="type_list" termsid="1" id="1">
     * {$data.total}
     * </links>
     * 
     * type_list
      +----------------------------------------------------------
     * @param string $attr 标签属性
     * @param string $content  标签内容
     */
    public function _links($attr, $content) {
        static $_iterateParseCache = array();
        //如果已经解析过，则直接返回变量值
        $cacheIterateId = md5($attr . $content);
        if (isset($_iterateParseCache[$cacheIterateId]))
            return $_iterateParseCache[$cacheIterateId];
        $tag = $this->parseXmlAttr($attr, 'content');
        /* 属性列表 */
        $num = (int) $tag['num']; //每页显示总数
        $return = empty($tag['return']) ? "data" : $tag['return']; //数据返回变量
        $action = $tag['action']; //方法
        
        $parseStr = '<?php';
        $parseStr .= ' $links_tag = TagLib("Links");';
        $parseStr .= ' if(method_exists($links_tag, "' . $action . '")):';
        $parseStr .= ' $' . $return . ' = $links_tag->' . $action . '(' . self::arr_to_html($tag) . ');';
        $parseStr .= ' endif;';
        $parseStr .= ' ?>';
        $parseStr .= $this->tpl->parse($content);
        $_iterateParseCache[$cacheIterateId] = $parseStr;
        return $parseStr;
    }
    
    /**
     * 推荐位标签
     *  +----------------------------------------------------------
     * type_list 获取友情链接列表
     * 格式：
     * <position action="position" posid="1">
     * {$data.total}
     * </position>
     * 
     * position
      +----------------------------------------------------------
     * @param string $attr 标签属性
     * @param string $content  标签内容
     */
    public function _position($attr, $content) {
        static $_iterateParseCache = array();
        //如果已经解析过，则直接返回变量值
        $cacheIterateId = md5($attr . $content);
        if (isset($_iterateParseCache[$cacheIterateId]))
            return $_iterateParseCache[$cacheIterateId];
        $tag = $this->parseXmlAttr($attr, 'content');
        /* 属性列表 */
        $num = (int) $tag['num']; //每页显示总数
        $return = empty($tag['return']) ? "data" : $tag['return']; //数据返回变量
        $action = $tag['action']; //方法
        
        $parseStr = '<?php';
        $parseStr .= ' $Position_tag = TagLib("Position");';
        $parseStr .= ' if(method_exists($Position_tag, "' . $action . '")):';
        $parseStr .= ' $' . $return . ' = $Position_tag->' . $action . '(' . self::arr_to_html($tag) . ');';
        $parseStr .= ' endif;';
        $parseStr .= ' ?>';
        $parseStr .= $this->tpl->parse($content);
        $_iterateParseCache[$cacheIterateId] = $parseStr;
        return $parseStr;
    }
    
    /**
     * get标签
     * 参数	 默认值	 必须	 说明
     * sql	 null	 是	 要执行的SQL语句
     * cache	 0	 否	 缓存时间，单位为秒 
     * page	 0	 否	 分页，通过变量把当前的分布传给P标签进行处理 $page
     * dbsource	 null	 否	 数据源，当你通过系统后台的数据源模块配置过数据源时，可把数据源名填写到这里，系统会去对应的数据源来读取数据。如果要读取本系统的数据请留空
     * return	 data	 否	  返回的数据的变量
     * @param type $attr
     * @param type $content 
     */
    public function _get($attr, $content) {
        $tag = $this->parseXmlAttr($attr, 'get');
        $sql = $tag['sql'];
        $cache = $tag['cache'];
        $page = $tag['page']; //当前分页
        $pagefun = empty($tag['pagefun']) ? "page" : $tag['pagefun']; //分页函数，默认page
        $pagetp = $tag['pagetp']; //分页模板
        $num = $tag['num']; //每页显示总数
        $return = empty($tag['return']) ? "data" : $tag['return']; //数据返回变量
        $tag['sql'] = str_replace("think_",C("DB_PREFIX"),$tag['sql']);

        $str = ' <?php ';
        //如果配置了数据源
        if ($datas['dbsource']) {
            
        } else {
            $str .= ' $get_db = new Model();';
        }
        $num = isset($num) && intval($num) > 0 ? intval($num) : 20;
        if (isset($page)) {
            if ($sql = preg_replace('/select([^from].*)from/i', "SELECT COUNT(*) as count FROM ", $tag['sql'])) {
                $str .= ' $count = $get_db->query("' . $sql . '");';
                $str .= ' $count = $count[0]["count"]; ';
                $str .= ' $_GET[C("VAR_PAGE")] = $page;';
                $str .= ' $pagetp = "' . $pagetp . '";';
                $str .= ' $_page_ = ' . $pagefun . '($count ,' . $num . ',$page,6,C("VAR_PAGE"),"",true,$pagetp);';
                //使用常量来保存总分页数，有个缺陷，如果不使用跳转的方式生成，会出现生成下一个栏目的时候无法对该常量进行重新赋值，使用跳转生成下一个栏目则没有这个问题！
                $str .= ' if (!defined("PAGES"))define("PAGES", $_page_->Total_Pages);';
                //_PAGES_ 用于解决上述所说的问题，这样可以根据$_GET["_PAGES_"] 来判断要生成多少页了
                $str .= ' $_GET["_PAGES_"] = $_page_->Total_Pages;';
                $str .= ' $pages = $_page_->show("default");';
                $str .= ' $pagesize = ' . $num . ';';
                $str .= ' $offset = ($page - 1) * $pagesize;';
                $str .= ' $' . $return . '=$get_db->query("' . $tag['sql'] . ' LIMIT ".$_page_->firstRow.",".$_page_->listRows." ");';
            }
        } else {
            $str .= ' $' . $return . '=$get_db->query("' . $tag['sql'] . ' LIMIT ' . $num . ' ");';
        }
        $str .= '  ?>';
        $str .= $this->tpl->parse($content);
        return $str;
    }

    /**
     * 转换数据为HTML代码
     * @param array $data 数组
     */
    private static function arr_to_html($data) {
        if (is_array($data)) {
            $str = 'array(';
            foreach ($data as $key => $val) {
                if (is_array($val)) {
                    $str .= "'$key'=>" . self::arr_to_html($val) . ",";
                } else {
                    if (strpos($val, '$') === 0) {
                        $str .= "'$key'=>$val,";
                    } else {
                        $str .= "'$key'=>'" . new_addslashes($val) . "',";
                    }
                }
            }
            return $str . ')';
        }
        return false;
    }

}

?>
